﻿using System;
using System.Collections.Generic;
using System.Linq;
using T.FAS.Runtime.Metadata.Entity;
using T.FAS.Runtime.Base.Entity;
using T.FAS.Runtime.Expression.Entity;
using T.FAS.Runtime.Metadata.SPI;
using System.Text;
using T.FAS.Runtime.Metadata.Entity.DataModel;
using ActionType = T.FAS.Runtime.Metadata.Entity.ActionType;
using T.ServiceComponent.Kernel.Service;

namespace T.FAS.Runtime.Action.ExpressionPlugin
{
    public class ActionDetailExpProvider : BaseProvider, IExprProvider
    {
        public List<ExprItem> GetExprChildrenItems(ExprItem item, bool IsContainExt, string projectBranchId)
        {
            if (item == null)
                throw new ArgumentNullException("ActionDetailExpProvider.GetExprChildrenItems.item");
            UpdateExprItemChildren(item, IsContainExt, projectBranchId);
            return item.Children;
        }
        public List<ExprItem> GetExprChildrenItems(List<ExprItem> item, bool IsContainExt, string projectBranchId)
        {
            if (item == null || item.Count <= 0)
                return null;
            GetExprChildrenItemsParallel(item, IsContainExt, projectBranchId);
            return item;
        }
        private void GetExprChildrenItemsParallel(List<ExprItem> items, bool IsContainExt, string projectBranchId)
        {
            if (items.Count > 50)
            {
                int parallelCount = items.Count / 5;
                List<List<ExprItem>> groupItems = new List<List<ExprItem>>();
                double groupCount = Math.Ceiling((double)items.Count / parallelCount);
                for (int i = 0; i < groupCount; i++)
                {
                    var subList = items.Skip(i * parallelCount).Take(parallelCount).ToList();
                    groupItems.Add(subList);
                }
                var context = ContextHelper.GetContext().Clone() as DefaultContext;
                groupItems.AsParallel().ForAll(t =>
                {
                    ContextHelper.SetContext(context);
                    BatchGetExprChildrenItems(t, IsContainExt, projectBranchId);
                });
            }
            else
            {
                BatchGetExprChildrenItems(items, IsContainExt, projectBranchId);
            }
        }
        private void BatchGetExprChildrenItems(List<ExprItem> items, bool IsContainExt, string projectBranchId)
        {
            int index = 0;
            foreach (var i in items)
            {
                if (i.IsDelete)
                    continue;
                try
                {
                    //DateTime start = DateTime.Now;
                    BuildExprItemOneByOne(IsContainExt, i, projectBranchId);
                    //DateTime end = DateTime.Now;
                    //LogUtil.Log(UserUtil.GetCurrentUserName()+ "," +(end-start).TotalMilliseconds +","+index);
                }
                catch (Exception ex)
                {
                    i.ItemType = ItemType.Error;
                    i.DisplayName = ex.Message;
                }
            }
        }

        public List<ExprItem> GetExprItems(string type, string typeId, string exprMetaDataID)
        {
            return new List<ExprItem>();
        }
        /// <summary>
        /// 构造与表达式结构一致的TResult结构，提供给前端绑定用
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        public TRecord BuildTResultSchema(ExprItem item, string projectBranchId = "")
        {
            var result = new TRecord();
            var schema = UpdateExprItemChildren(item, false, projectBranchId);
            var propertiesDic = new Dictionary<string, object>();
            propertiesDic.Add("ActionID", schema.ActionID);
            propertiesDic.Add("ActionCode", schema.ActionCode);
            propertiesDic.Add("ActionName", schema.ActionName);
            if (item.Children != null && item.Children.Count > 0)
            {
                item.Children.ForEach(expr =>
                {
                    if (expr.IsLeaf)
                    {
                        propertiesDic.Add(expr.Code, "");
                    }
                    else
                    {
                        //propertiesDic.Add(TUtil.GetPropertyName(expr.Code,expr.ValueType==DataType.List), BuildRecordSchemaByExprItem(expr.Children));
                        propertiesDic.Add(expr.Code, BuildRecordSchemaByExprItem(expr.Children));
                    }
                });
            }
            result = new TRecord(propertiesDic);
            return result;
        }
        public List<ExprItem> GetExprIncrementalItems(string exprMetaDataID, DateTime dateTime)
        {
            return new List<ExprItem>();
        }

        #region 内部方法

        //更新Action表达式项-顶级节点（代表元数据本身）
        private void BuildExprItemOneByOne(bool IsContainExt, ExprItem i, string projectBranchID = "")
        {
            var action = base.GetMetaDataContentByType(i.ID, ProviderMetadataType.Action, projectBranchID) as ActionMetaData;
            if (action != null)
            {
                i.Code = action.Code;
                i.Name = action.Name;
                i.IsLeaf = true;
                i.HelpInfo = $"<div ad><div at>服务动作：</div>{action.Code}，{action.Name}</div>";// action.Name;
                i.ItemType = ItemType.Action;
                i.ValueType = action.ReturnValueType.Equals(ReturnValueType.List) ? DataType.List : DataType.Record;
                //构造入参集合
                var inParams = action.MethodParams.FindAll(x => x.ParamType == ParamType.In);
                inParams.ForEach(p =>
                {
                    int index = 0;
                    var exprFuncItemParam = new ExprFuncItemParam()
                    {
                        ID = Guid.NewGuid().ToString(),
                        ExprItemID = i.ID,
                        Code = p.Code,
                        Name = p.Name,
                        SortOrder = index,
                        DataType = p.SysDataType,
                    };
                    if (p.ParamSourceType == ParamSourceType.EO || p.ParamSourceType == ParamSourceType.DO || p.ParamSourceType == ParamSourceType.SDO || p.ParamSourceType == ParamSourceType.DQ ||
                     p.ParamSourceType == ParamSourceType.CDO)
                    {
                        if (!string.IsNullOrEmpty(p.SourceID))
                        {
                            var metaData = base.GetMetaData(p.SourceID, projectBranchID);
                            var expItem = new ExprItem();
                            BuildInparamExprItem(expItem, IsContainExt, p, metaData.Content);
                            exprFuncItemParam.ExprExt = expItem;
                        }
                    }
                    i.ExprFuncItemParamList.Add(exprFuncItemParam);
                    index++;
                });
                i.DisplayName = "Action." + action.Code + $"({string.Join(",", inParams.Select(p => p.Code))})";
                i.ExprMetaDataID = action.IsClientAction ? "ClientAction" : i.ExprMetaDataID;

                UpdateExprItemForActionWithReturnValue(i, action, IsContainExt, projectBranchID);
            }
        }

        private void BuildInparamExprItem(ExprItem parentNode, bool IsContainExt, ActionMetaDataMethodParam inParam, IMetaDataContent metaDataContent)
        {
            TEntity entity = null;
            switch (inParam.ParamSourceType)
            {
                case ParamSourceType.EO:
                    {
                        var metaData = metaDataContent as EntityObject;
                        if (metaData != null)
                            entity = metaData.BuildSchema().Entity;
                        break;
                    }
                case ParamSourceType.DO:
                case ParamSourceType.SDO:
                    {
                        var metaData = metaDataContent as DataObject;
                        if (metaData != null)
                            entity = metaData.BuildSchema().Entity;
                        break;
                    }
                case ParamSourceType.DQ:
                    {
                        var metaData = metaDataContent as DataQuery;
                        if (metaData != null)
                            entity = metaData.BuildSchema().Entity;
                        break;
                    }
                case ParamSourceType.CDO:
                    {
                        var metaData = metaDataContent as CompositeDataObject;
                        if (metaData != null)
                            entity = metaData.BuildSchema().Entity;
                        break;
                    }
            }
            if (entity != null)
            {
                BuildTEntityExprItem(parentNode, entity, IsContainExt, metaDataContent: metaDataContent);
            }
        }

        /// <summary>
        /// 针对有返回值的Action进行ExprItem的更新
        /// </summary>
        /// <param name="i"></param>
        /// <param name="action"></param>
        private void UpdateExprItemForActionWithReturnValue(ExprItem exprItem, ActionMetaData action, bool IsContainExt = false, string projectBranchID = "")
        {
            if (action.MethodParams != null && action.MethodParams.Count > 0)
            {
                var outParam = action.MethodParams.Find(x => x.ParamType == ParamType.Out);
                if (outParam != null)
                {
                    var schema = new TSchema();
                    var schemaConvertType = SPI.TSchemaConvertType.EO;
                    IMetaDataContent outParamRefTypeMetaDataContent = default;
                    switch (outParam.ParamSourceType)
                    {
                        case ParamSourceType.DQ:
                            {
                                if (string.IsNullOrEmpty(outParam.SourceID))
                                    return;
                                schemaConvertType = SPI.TSchemaConvertType.DQ;
                                //var DQMetaData = new DataQueryManager().GetMetaDataContent(outParam.SourceID) as DataQuery;
                                var DQMetaData = new DevMetadataService().GetMetadata(outParam.SourceID, projectBranchID) as DataQuery;
                                if (DQMetaData == null)
                                    return;
                                outParamRefTypeMetaDataContent = DQMetaData;
                                schema = DQMetaData.BuildSchema();
                            }
                            break;
                        case ParamSourceType.CDO:
                            {
                                if (string.IsNullOrEmpty(outParam.SourceID))
                                    return;
                                schemaConvertType = SPI.TSchemaConvertType.CDO;
                                //var CDOMetaData = new CompositeDataObjectManager().GetMetaDataContent(outParam.SourceID) as CompositeDataObject;
                                var CDOMetaData = new DevMetadataService().GetMetadata(outParam.SourceID, projectBranchID) as CompositeDataObject;
                                if (CDOMetaData == null)
                                    return;
                                outParamRefTypeMetaDataContent = CDOMetaData;
                                schema = CDOMetaData.BuildSchema();
                            }
                            break;
                        case ParamSourceType.DO:
                        case ParamSourceType.SDO:
                            {
                                if (string.IsNullOrEmpty(outParam.SourceID))
                                    return;
                                schemaConvertType = SPI.TSchemaConvertType.DO;
                                //var DOMetaData = new DataObjectManager().GetMetaDataContent(outParam.SourceID) as DataObject;
                                var DOMetaData = new DevMetadataService().GetMetadata(outParam.SourceID, projectBranchID) as DataObject;
                                if (DOMetaData == null)
                                    return;
                                outParamRefTypeMetaDataContent = DOMetaData;
                                schema = DOMetaData.BuildSchema();
                            };
                            break;
                        case ParamSourceType.EO:
                            {
                                if (string.IsNullOrEmpty(outParam.SourceID))
                                    return;
                                schemaConvertType = SPI.TSchemaConvertType.EO;
                                //var EOMetaData = new EntityObjectManager().GetMetaDataContent(outParam.SourceID) as EntityObject; 
                                var EOMetaData = new DevMetadataService().GetMetadata(outParam.SourceID, projectBranchID) as EntityObject;
                                if (EOMetaData == null)
                                    return;
                                outParamRefTypeMetaDataContent = EOMetaData;
                                schema = EOMetaData.BuildSchema();
                            }
                            break;
                        case ParamSourceType.Basic:
                            {
                                schema = BasicTypeData.BuildSchema(outParam.ParamValueType);
                            }
                            break;
                        default:
                            {
                                schema = new TSchema() { Entity = new TEntity() };
                                action.ActionSchemaRefresh(schema);
                                UpdateExprItemForBasicDataType(exprItem, action, schema, IsContainExt: IsContainExt);
                                UpdateHelpInfo(exprItem);
                                return;
                            }

                    }
                    //var schema = TSchemaConverter.ConvertToTSchema(schemaConvertType, outParam.SourceID);
                    action.ActionSchemaRefresh(schema);
                    UpdateExprItem(exprItem, action, schema, IsContainExt: IsContainExt, outParamRefTypeMetaDataContent: outParamRefTypeMetaDataContent);
                    UpdateHelpInfo(exprItem);
                }
            }
        }

        private TRecord BuildRecordSchemaByExprItem(List<ExprItem> items)
        {
            var propertiesDic = new Dictionary<string, object>();
            foreach (var item in items)
            {
                if (item.IsLeaf)
                {
                    propertiesDic.Add(item.Code, "");
                }
                else
                {
                    if (item.Children != null)
                    {
                        var subPropertiesDic = new Dictionary<string, object>();
                        foreach (var expr in item.Children)
                        {
                            if (expr.IsLeaf)
                            {
                                subPropertiesDic.Add(expr.Code, "");
                            }
                            else
                            {
                                var childRecord = BuildRecordSchemaByExprItem(expr.Children);
                                subPropertiesDic.Add(expr.Code, childRecord);
                            }
                        }
                        var subRecord = new TRecord(subPropertiesDic);
                        propertiesDic.Add(item.Code, subRecord);
                    }
                    else
                    {
                        propertiesDic.Add(item.Code, "");
                    }
                }
            }
            return new TRecord(propertiesDic);
        }
        private TSchema UpdateExprItemChildren(ExprItem item, bool IsContainExt = false, string projectBranchID = "")
        {
            if (item.ItemType == ItemType.Action)
            {
                return BuildTSchemaForAction(item, IsContainExt, projectBranchID);
            }
            else
            {
                return BuildTSchemaForOther(item, IsContainExt, projectBranchID);
            }
        }
        private TSchema BuildTSchemaForOther(ExprItem item, bool IsContainExt = false, string projectBranchID = "")
        {
            TSchema scheme = new TSchema();
            switch (item.ItemType)
            {
                case ItemType.DO:
                    {
                        var dataobject = base.GetMetaDataContentByType(item.ID, ProviderMetadataType.DO, projectBranchID) as DataObject;
                        if (dataobject == null)
                            throw new Exception($"DO:{item.ID} 获取元数据实体失败，分支:{projectBranchID}");
                        UpdateDataObjectExprItem(item, dataobject, IsContainExt);
                    }
                    break;
                case ItemType.EO:
                    {
                        var eo = base.GetMetaDataContentByType(item.ID, ProviderMetadataType.EO, projectBranchID) as EntityObject;
                        if (eo == null)
                            throw new Exception($"EO:{item.ID} 获取元数据实体失败，分支:{projectBranchID}");
                        UpdateEntityObjectExprItem(item, eo, IsContainExt);
                    }
                    break;
                case ItemType.CDO:
                    {
                        var cdo = base.GetMetaDataContentByType(item.ID, ProviderMetadataType.CDO, projectBranchID) as CompositeDataObject;
                        if (cdo == null)
                            throw new Exception($"CDO:{item.ID} 获取元数据实体失败，分支:{projectBranchID}");
                        UpdateCDOExprItem(item, cdo, IsContainExt);
                    }
                    break;
                case ItemType.DataQuery:
                default:
                    {
                        var dq = base.GetMetaDataContentByType(item.ID, ProviderMetadataType.DQ, projectBranchID) as DataQuery;
                        if (dq == null)
                            throw new Exception($"DQ:{item.ID} 获取元数据实体失败，分支:{projectBranchID}");
                        UpdateDQExprItem(item, dq, IsContainExt);
                    }
                    break;
            }
            return scheme;
        }
        /// <summary>
        /// 为DO类型单独创建ExprItem结构
        /// </summary>
        /// <param name="item"></param>
        /// <param name="dataobject"></param>
        private void UpdateDataObjectExprItem(ExprItem item, DataObject dataobject, bool IsContainExt = false)
        {
            IRefSchemaEntity refSchemaEntity = RefSchemaExprUtil.GetRefSchemaEntity(dataobject);
            item.Children = new List<ExprItem>();
            if (item.ValueType == DataType.List)
            {
                var currentNode = new ExprItem()
                {
                    ID = "Current",
                    Code = "Current",
                    Name = "Current",
                    ParentID = item.ID,
                    DisplayName = item.DisplayName + ".Current",
                    //DisplayName = item.DisplayName + "."+TUtil.GetPropertyName(dataobject.Code,false),
                    DataModels = dataobject.Code,
                    ExprMetaDataID = item.ExprMetaDataID,
                    IsLeaf = false,
                    SortOrder = 0,
                    ValueType = DataType.Record,
                    ItemType = ItemType.Object,
                    RefSchemaExpr = RefSchemaExprUtil.GetExpr(dataobject.GetTopRefSchemaExpr()),
                };
                currentNode.Children = new List<ExprItem>();
                var index = 0;
                foreach (var column in dataobject.Columns)
                {
                    string columnExpr = column.GetRefSchemaExpr(dataobject);
                    var columnNode = new ExprItem()
                    {
                        ID = column.ID,
                        Code = column.ColumnName,
                        Name = column.DisplayName,
                        ParentID = currentNode.ID,
                        DisplayName = currentNode.DisplayName + "." + column.ColumnName,
                        DataModels = column.ColumnName,
                        ExprMetaDataID = item.ExprMetaDataID,
                        IsLeaf = true,
                        SortOrder = index,
                        ValueType = (DataType)Enum.Parse(typeof(DataType), column.IsFkColumn ? column.GetFKDataObjectPkColumnApplicationDataType() : column.ApplicationDataType, true),
                        ItemType = ItemType.Attribute,
                        RefSchemaExpr = RefSchemaExprUtil.GetExpr(columnExpr),
                        RefSchemaExprValue = RefSchemaExprUtil.GetExprValue(refSchemaEntity, columnExpr, true),
                    };
                    //是否需要包含扩展属性
                    if (IsContainExt)
                    {
                        var extDic = new Dictionary<string, object>();
                        extDic.Add(ExpressionPluginManager.ExprExt_Length, column.Length);
                        extDic.Add(ExpressionPluginManager.ExprExt_IsRequired, column.IsNullable ? false : true);
                        extDic.Add(ExpressionPluginManager.ExprExt_Precision, column.Precision);
                        extDic.Add(ExpressionPluginManager.ExprExt_DefaultValue, column.DefaultValue);
                        columnNode.ExprExt = extDic;
                    }
                    currentNode.Children.Add(columnNode);
                    index++;
                }
                item.Children = new List<ExprItem>() { currentNode };
            }
            else if (item.ValueType == DataType.Record)
            {
                var index = 0;
                foreach (var column in dataobject.Columns)
                {
                    string columnExpr = column.GetRefSchemaExpr(dataobject);
                    var columnNode = new ExprItem()
                    {
                        ID = column.ID,
                        Code = column.ColumnName,
                        Name = column.DisplayName,
                        ParentID = item.ID,
                        DisplayName = item.DisplayName + "." + column.ColumnName,
                        DataModels = column.ColumnName,
                        ExprMetaDataID = item.ExprMetaDataID,
                        IsLeaf = true,
                        SortOrder = index,
                        ValueType = (DataType)Enum.Parse(typeof(DataType), column.IsFkColumn ? column.GetFKDataObjectPkColumnApplicationDataType() : column.ApplicationDataType, true),
                        ItemType = ItemType.Attribute,
                        RefSchemaExpr = RefSchemaExprUtil.GetExpr(columnExpr),
                        RefSchemaExprValue = RefSchemaExprUtil.GetExprValue(refSchemaEntity, columnExpr, true),
                    };
                    //是否需要包含扩展属性
                    if (IsContainExt)
                    {
                        var extDic = new Dictionary<string, object>();
                        extDic.Add(ExpressionPluginManager.ExprExt_Length, column.Length);
                        extDic.Add(ExpressionPluginManager.ExprExt_IsRequired, column.IsNullable ? false : true);
                        extDic.Add(ExpressionPluginManager.ExprExt_Precision, column.Precision);
                        extDic.Add(ExpressionPluginManager.ExprExt_DefaultValue, column.DefaultValue);
                        columnNode.ExprExt = extDic;
                    }
                    item.Children.Add(columnNode);
                    index++;
                }
            }
        }


        /// <summary>
        /// 为EO类型单独创建ExprItem结构
        /// </summary>
        /// <param name="item"></param>
        /// <param name="entityObject"></param>
        private void UpdateEntityObjectExprItemV1(ExprItem item, EntityObject entityObject, bool IsContainExt)
        {
            
            IRefSchemaEntity refSchemaEntity = RefSchemaExprUtil.GetRefSchemaEntity(entityObject);
            item.Children = new List<ExprItem>();
            if (item.ValueType == DataType.List)
            {
                var currentNode = new ExprItem()
                {
                    ID = "Current",
                    Code = "Current",
                    Name = "Current",
                    ParentID = item.ID,
                    DisplayName = item.DisplayName + ".Current",
                    DataModels = entityObject.Code,
                    ExprMetaDataID = item.ExprMetaDataID,
                    IsLeaf = false,
                    SortOrder = 0,
                    ValueType = DataType.Record,
                    ItemType = ItemType.Object,
                    RefSchemaExpr = RefSchemaExprUtil.GetExpr(entityObject.GetTopRefSchemaExpr()),
                };
                currentNode.Children = new List<ExprItem>();
                var index = 0;
                foreach (EntityObjectAttribute attr in entityObject.EntityObjectAttributes)
                {
                    var attrExpr = attr.GetRefSchemaExpr(entityObject);
                    var attrNode = new ExprItem()
                    {
                        ID = attr.ID,
                        Code = attr.Code,
                        Name = attr.Name,
                        ParentID = currentNode.ID,
                        DisplayName = currentNode.DisplayName + "." + attr.Code,
                        DataModels = attr.Code,
                        ExprMetaDataID = item.ExprMetaDataID,
                        IsLeaf = true,
                        SortOrder = index,
                        ValueType = (DataType)Enum.Parse(typeof(DataType), attr.DataType, true),
                        ItemType = ItemType.Attribute,
                        RefSchemaExpr = RefSchemaExprUtil.GetExpr(attrExpr),
                        RefSchemaExprValue = RefSchemaExprUtil.GetExprValue(refSchemaEntity, attrExpr, true),
                    };
                    //是否需要包含扩展属性
                    //if (IsContainExt)
                    //{
                    //    var extDic = new Dictionary<string, object>();
                    //    extDic.Add(ExpressionPluginManager.ExprExt_Length, attr.Length);
                    //    extDic.Add(ExpressionPluginManager.ExprExt_IsRequired, attr.IsRequired);
                    //    extDic.Add(ExpressionPluginManager.ExprExt_Precision, attr.Precision);
                    //    extDic.Add(ExpressionPluginManager.ExprExt_DefaultValue, attr.DefaultValue);
                    //    attrNode.ExprExt = extDic;
                    //}
                    currentNode.Children.Add(attrNode);
                    index++;
                }
                item.Children = new List<ExprItem>() { currentNode };
            }
            else if (item.ValueType == DataType.Record)
            {
                var index = 0;
                foreach (EntityObjectAttribute attr in entityObject.EntityObjectAttributes)
                {
                    var attrExpr = attr.GetRefSchemaExpr(entityObject);
                    var columnNode = new ExprItem()
                    {
                        ID = attr.ID,
                        Code = attr.Code,
                        Name = attr.Name,
                        ParentID = item.ID,
                        DisplayName = item.DisplayName + "." + attr.Code,
                        DataModels = attr.Code,
                        ExprMetaDataID = item.ExprMetaDataID,
                        IsLeaf = true,
                        SortOrder = index,
                        ValueType = (DataType)Enum.Parse(typeof(DataType), attr.DataType, true),
                        ItemType = ItemType.Attribute,
                        RefSchemaExpr = RefSchemaExprUtil.GetExpr(attrExpr),
                        RefSchemaExprValue = RefSchemaExprUtil.GetExprValue(refSchemaEntity, attrExpr, true),
                    };
                    //是否需要包含扩展属性
                    //if (IsContainExt)
                    //{
                    //    var extDic = new Dictionary<string, object>();
                    //    extDic.Add(ExpressionPluginManager.ExprExt_Length, attr.Length);
                    //    extDic.Add(ExpressionPluginManager.ExprExt_IsRequired, attr.IsRequired);
                    //    extDic.Add(ExpressionPluginManager.ExprExt_Precision, attr.Precision);
                    //    extDic.Add(ExpressionPluginManager.ExprExt_DefaultValue, attr.DefaultValue);
                    //    columnNode.ExprExt = extDic;
                    //}
                    item.Children.Add(columnNode);
                    index++;
                }
            }
            
        } /// <summary>
          /// 为EO类型单独创建ExprItem结构
          /// </summary>
          /// <param name="item"></param>
          /// <param name="entityObject"></param>
        private void UpdateEntityObjectExprItem(ExprItem item, EntityObject entityObject, bool IsContainExt)
        {
            var schema = entityObject.BuildSchema();
            var startEntity = SearchSpecifiedEntityRecursiveForCDO(item, schema.Entity);
            item.Children = new List<ExprItem>();
            if (item.ValueType == DataType.List)
            {
                var currentCode = "Current";
                var currentNode = new ExprItem()
                {
                    ID = currentCode,
                    Code = currentCode,
                    Name = currentCode,
                    ParentID = item.ID,
                    DisplayName = item.DisplayName + "." + currentCode,
                    DataModels = entityObject.Code,
                    ExprMetaDataID = item.ExprMetaDataID,
                    IsLeaf = false,
                    SortOrder = 0,
                    ValueType = DataType.Record,
                    ItemType = ItemType.Object,
                    RefSchemaExpr = RefSchemaExprUtil.GetExpr(entityObject.GetTopRefSchemaExpr()),
                };
                BuildTEntityExprItem(currentNode, startEntity, IsContainExt, entityObject);
                item.Children = new List<ExprItem>() { currentNode };
            }
            else if (item.ValueType == DataType.Record)
            {
                BuildTEntityExprItem(item, startEntity, IsContainExt, entityObject);
            }
        }

        /// <summary>
        /// 为cdo类型单独创建ExprItem结构
        /// </summary>
        /// <param name="item"></param>
        /// <param name="cdo"></param>
        private void UpdateCDOExprItem(ExprItem item, CompositeDataObject cdo, bool IsContainExt = false)
        {
            var schema = cdo.BuildSchema();
            var startEntity = SearchSpecifiedEntityRecursiveForCDO(item, schema.Entity);
            if (item.ValueType == DataType.List)
            {
                var currentCode = "Current";
                //List的需要构造Current节点
                var currentNode = new ExprItem()
                {
                    ID = currentCode,
                    Code = currentCode,
                    Name = currentCode,
                    DataModels = cdo.Code,
                    DisplayName = item.DisplayName + "." + currentCode,
                    //DisplayName = item.DisplayName + "." + TUtil.GetPropertyName(currentCode,true),
                    ExprMetaDataID = item.ExprMetaDataID,
                    IsLeaf = false,
                    ItemType = ItemType.Object,
                    ParentID = item.ID,
                    SortOrder = 0,
                    ValueType = DataType.Record,
                    Children = new List<ExprItem>(),
                    RefSchemaExpr = RefSchemaExprUtil.GetExpr(cdo.GetTopRefSchemaExpr()),
                };
                BuildTEntityExprItem(currentNode, startEntity, IsContainExt, cdo);
                item.Children = new List<ExprItem>() { currentNode };
            }
            else
            {
                BuildTEntityExprItem(item, startEntity, IsContainExt, cdo);
            }
        }
        /// <summary>
        /// 为dq类型单独创建ExprItem结构
        /// </summary>
        /// <param name="item"></param>
        /// <param name="dq"></param>
        /// <param name="IsContainExt"></param>
        private void UpdateDQExprItem(ExprItem item, DataQuery dq, bool IsContainExt = false)
        {
            var schema = dq.BuildSchema();
            if (item.ValueType == DataType.List)
            {
                var currentCode = "Current";
                //List的需要构造Current节点
                var currentNode = new ExprItem()
                {
                    ID = currentCode,
                    Code = currentCode,
                    Name = currentCode,
                    DataModels = dq.Code,
                    DisplayName = item.DisplayName + "." + currentCode,
                    ExprMetaDataID = item.ExprMetaDataID,
                    IsLeaf = false,
                    ItemType = ItemType.Object,
                    ParentID = item.ID,
                    SortOrder = 0,
                    ValueType = DataType.Record,
                    Children = new List<ExprItem>(),
                    RefSchemaExpr = RefSchemaExprUtil.GetExpr(dq.GetTopRefSchemaExpr()),
                };
                BuildTEntityExprItem(currentNode, schema.Entity, IsContainExt, dq);
                item.Children = new List<ExprItem>() { currentNode };
            }
            else
            {
                BuildTEntityExprItem(item, schema.Entity, IsContainExt, dq);
            }
        }

        /// <summary>
        /// 递归查找指定起始的DO节点
        /// </summary>
        /// <param name="item"></param>
        /// <param name="entity"></param>
        /// <returns></returns>
        private TEntity SearchSpecifiedEntityRecursiveForCDO(ExprItem item, TEntity entity)
        {
            if (string.IsNullOrEmpty(item.ExprMetaDataAlias))
                return entity;
            else
            {
                if (entity.MetadataCode.Equals(item.ExprMetaDataAlias, StringComparison.OrdinalIgnoreCase))
                {
                    return entity;
                }
                else
                {
                    if (entity != null && entity.Attributes != null && entity.Attributes.Count > 0)
                    {
                        var entities = entity.Attributes.FindAll(x => x.Entity != null);
                        if (entities != null && entities.Count > 0)
                        {
                            foreach (var subEntity in entities)
                            {
                                var destination = SearchSpecifiedEntityRecursiveForCDO(item, subEntity.Entity);
                                if (destination != null)
                                    return destination;
                            }
                        }
                    }
                    return null;
                }
            }
        }

        private TSchema BuildTSchemaForAction(ExprItem item, bool IsContainExt = false, string projectBranchID = "")
        {
            var schema = new TSchema();
            var action = base.GetMetaDataContentByType(item.ID, ProviderMetadataType.Action, projectBranchID) as ActionMetaData;
            if (action != null)
            {
                if (action.ActionType == ActionType.CDO)
                {
                    var cdo = base.GetMetaDataContentByType(action.RelatedMetaDataID, ProviderMetadataType.CDO, projectBranchID) as CompositeDataObject;
                    schema = cdo.BuildSchema();
                    action.ActionSchemaRefresh(schema);
                    UpdateExprItem(item, action, schema, IsContainExt: IsContainExt);
                    UpdateHelpInfo(item);
                }
                else
                {
                    if (action.MethodParams != null && action.MethodParams.Count > 0)
                    {
                        var outParam = action.MethodParams.Find(x => x.ParamType == ParamType.Out);
                        if (outParam != null && outParam.ParamSourceType == ParamSourceType.EO)
                        {
                            var eo = base.GetMetaDataContentByType(outParam.SourceID, ProviderMetadataType.EO, projectBranchID) as EntityObject;
                            schema = eo.BuildSchema();
                            action.ActionSchemaRefresh(schema);
                            UpdateExprItem(item, action, schema, IsContainExt: IsContainExt);
                            UpdateHelpInfo(item);
                        }
                    }
                }
            }
            return schema;
        }

        private void UpdateExprItemForBasicDataType(ExprItem exprItem, ActionMetaData action, TSchema schema, string exprPreFix = "Action.", bool IsContainExt = false)
        {
            DataType dType = default;
            switch (action.ReturnValueType)
            {
                case ReturnValueType.List:
                    dType = DataType.List;
                    break;
                case ReturnValueType.Record:
                    dType = DataType.Record;
                    break;
                default:
                    return;
            }
            exprItem.Code = action.Code;
            exprItem.Name = action.Name;
            exprItem.IsLeaf = false;
            exprItem.HelpInfo = action.Name;
            exprItem.ItemType = ItemType.Action;
            exprItem.ValueType = action.ReturnValueType.Equals(ReturnValueType.List) ? DataType.List : DataType.Record;
            //构造入参集合
            exprItem.ExprFuncItemParamList = new List<ExprFuncItemParam>();
            var inParams = action.MethodParams.FindAll(x => x.ParamType == ParamType.In);
            inParams.ForEach(p =>
            {
                int index = 0;
                exprItem.ExprFuncItemParamList.Add(new ExprFuncItemParam()
                {
                    ID = Guid.NewGuid().ToString(),
                    ExprItemID = exprItem.ID,
                    Code = p.Code,
                    Name = p.Name,
                    SortOrder = index,
                    DataType = p.SysDataType,
                });
                index++;
            });

            exprItem.DisplayName = exprPreFix + action.Code + $"({string.Join(",", inParams.Select(p => p.Code))})";
            if (dType == DataType.List)
            {
                if (schema.Entity.ListTypeMethods != null)
                {
                    //增加List节点
                    schema.Entity.ListTypeMethods.OrderBy(x => x.SortOrder).ToList().ForEach(method =>
                    {
                        BuildListTypeMethodExprItem(exprItem, method, schema.Entity, true, IsContainExt);
                    });
                }
            }
            else if (dType == DataType.Record)
            {
                //增加Record节点
                var recordNode = new ExprItem()
                {
                    ID = "Record",
                    Code = "Record",
                    Name = "Record",
                    DisplayName = exprItem.DisplayName + ".Record",
                    ItemType = ItemType.Object,
                    ValueType = DataType.Record,
                    HelpInfo = action.Code + "Record",
                    SortOrder = 0,
                    ExprMetaDataID = exprItem.ExprMetaDataID,
                    ParentID = exprItem.ID,
                    IsLeaf = false,
                    DataModels = schema.Entity.MetadataCode,
                    RefSchemaExpr = RefSchemaExprUtil.GetExpr($"Schema.Action.{action.Code}"),
                };
                recordNode.DataModels = schema.Entity.MetadataCode;
                BuildTEntityExprItem(recordNode, schema.Entity, IsContainExt, action);
                exprItem.Children.Add(recordNode);
            }
        }

        private void UpdateExprItem(ExprItem exprItem, ActionMetaData action, TSchema schema, string exprPreFix = "Action.", bool IsContainExt = false, IMetaDataContent outParamRefTypeMetaDataContent = null)
        {
            if (schema == null)
                return;
            DataType dType = default;
            switch (action.ReturnValueType)
            {
                case ReturnValueType.List:
                    dType = DataType.List;
                    break;
                case ReturnValueType.Record:
                    dType = DataType.Record;
                    break;
                default:
                    return;
            }
            exprItem.Code = action.Code;
            exprItem.Name = action.Name;
            exprItem.IsLeaf = false;
            exprItem.HelpInfo = action.Name;
            exprItem.ItemType = ItemType.Action;
            exprItem.ValueType = action.ReturnValueType.Equals(ReturnValueType.List) ? DataType.List : DataType.Record;
            exprItem.RefSchemaExpr = RefSchemaExprUtil.GetExpr(schema.Entity.RefSchemaExpr);
            //exprItem.RefSchemaExprValue = RefSchemaExprUtil.GetExpr(schema.Entity.RefSchemaExpr);

            //填充DataModels
            if (schema.MetadataType == TEntityType.DQ)
            {
                if (schema.Entity != null && schema.Entity.Attributes != null && schema.Entity.Attributes.Count > 0)
                {
                    var subEntities = schema.Entity.Attributes.FindAll(x => x.DataType == DataType.List || x.DataType == DataType.Record);
                    if (subEntities != null && subEntities.Count > 0)
                    {
                        exprItem.DataModels = string.Join(",", subEntities.Select(x => x.MetadataCode));
                    }
                }
            }
            else
            {
                if (schema.Entity != null)
                {
                    exprItem.DataModels = schema.Entity.MetadataCode;
                }
            }

            var inParams = action.MethodParams.FindAll(x => x.ParamType == ParamType.In);
            //构造入参集合
            if (exprItem.ExprFuncItemParamList == null || exprItem.ExprFuncItemParamList.Count <= 0)
            {
                exprItem.ExprFuncItemParamList = new List<ExprFuncItemParam>();
                inParams.ForEach(p =>
                {
                    int index = 0;
                    exprItem.ExprFuncItemParamList.Add(new ExprFuncItemParam()
                    {
                        ID = Guid.NewGuid().ToString(),
                        ExprItemID = exprItem.ID,
                        Code = p.Code,
                        Name = p.Name,
                        SortOrder = index,
                        DataType = p.SysDataType,
                    });
                    index++;
                });
            }

            exprItem.DisplayName = exprPreFix + action.Code + $"({string.Join(",", inParams.Select(p => p.Code))})";
            if (dType == DataType.List)
            {
                if (schema.Entity.ListTypeMethods != null)
                {
                    //增加List节点
                    schema.Entity.ListTypeMethods.OrderBy(x => x.SortOrder).ToList().ForEach(method =>
                      {
                          BuildListTypeMethodExprItem(exprItem, method, schema.Entity, true, IsContainExt, metaDataContent: outParamRefTypeMetaDataContent);
                      });
                }
            }
            else if (dType == DataType.Record)
            {
                //增加Record节点
                var recordNode = new ExprItem()
                {
                    ID = "Record",
                    Code = "Record",
                    Name = "Record",
                    DisplayName = exprItem.DisplayName + ".Record",
                    ItemType = ItemType.Object,
                    ValueType = DataType.Record,
                    HelpInfo = action.Code + "Record",
                    SortOrder = 0,
                    ExprMetaDataID = exprItem.ExprMetaDataID,
                    ParentID = exprItem.ID,
                    IsLeaf = false,
                    DataModels = schema.Entity.MetadataCode,
                    RefSchemaExpr = RefSchemaExprUtil.GetExpr(schema.Entity.RefSchemaExpr)
                };
                recordNode.DataModels = schema.Entity.MetadataCode;
                BuildTEntityExprItem(recordNode, schema.Entity, IsContainExt, metaDataContent: outParamRefTypeMetaDataContent);
                exprItem.Children.Add(recordNode);
            }
        }

        private void BuildListTypeMethodExprItem(ExprItem parentItem, TListMethod method, TEntity entity, bool isRoot = false, bool IsContainExt = false, TAttribute attr = null, IMetaDataContent metaDataContent = null)
        {
            var item = new ExprItem();
            if (!isRoot && method.Code.ToLower().Equals("list"))
            {
                //改动：EO主子节点中子节点属性为List集合时，不应该增加_List后缀，应完全以业务返回的Json结构一致
                string displayName = (attr != null && attr.Entity != null && attr.Entity.MetadataType.Equals(TEntityType.EO) ? attr.Code : entity.MetadataCode);
                if (attr.Entity.MetadataType.Equals(TEntityType.EO))
                {
                    //displayName = parentItem.DisplayName + "." + displayName;     //暂时屏蔽掉
                    displayName = parentItem.DisplayName + "." + TUtil.GetPropertyName(displayName, true);
                }
                else
                {
                    displayName = parentItem.DisplayName + "." + TUtil.GetPropertyName(displayName, true);
                }

                item = new ExprItem()
                {
                    ID = (attr != null && attr.Entity != null && attr.Entity.MetadataType.Equals(TEntityType.EO) ? attr.ID : entity.MetadataID),
                    Code = (attr != null && attr.Entity != null && attr.Entity.MetadataType.Equals(TEntityType.EO) ? attr.Code : entity.MetadataCode),
                    Name = (attr != null && attr.Entity != null && attr.Entity.MetadataType.Equals(TEntityType.EO) ? attr.Name : entity.MetadataName),
                    //DisplayName = parentItem.DisplayName + "." + entity.MetadataCode,
                    DisplayName = displayName,
                    ValueType = method.ReturnDataType,
                    ItemType = ItemType.Object,
                    SortOrder = method.SortOrder,
                    ExprMetaDataID = parentItem.ExprMetaDataID,
                    ParentID = parentItem.ID,
                    IsLeaf = (method.SubMethods == null || method.SubMethods.Count <= 0) ? true : false,
                    DataModels = entity.MetadataCode,
                    RefSchemaExpr = RefSchemaExprUtil.GetExpr(entity.RefSchemaExpr),
                };
            }
            else
            {
                item = new ExprItem()
                {
                    ID = Guid.NewGuid().ToString(),
                    Code = method.Code,
                    Name = method.Code,
                    DisplayName = parentItem.DisplayName + "." + method.Code,
                    ValueType = method.ReturnDataType,
                    ItemType = ItemType.Object,
                    HelpInfo = parentItem.DisplayName + "." + method.Code,
                    SortOrder = method.SortOrder,
                    ExprMetaDataID = parentItem.ExprMetaDataID,
                    ParentID = parentItem.ID,
                    IsLeaf = (method.SubMethods == null || method.SubMethods.Count <= 0) ? true : false,
                    RefSchemaExpr = RefSchemaExprUtil.GetExpr(entity.RefSchemaExpr),
                };
                if (method.Code.ToLower().Equals("list"))
                {
                    //item.DisplayName = parentItem.DisplayName + "." + TUtil.GetPropertyName(entity.MetadataCode,true);
                    //item.Code = entity.MetadataCode;
                    //item.Name = entity.MetadataCode;
                }
                if (entity.Attributes != null && entity.Attributes.Count > 0)
                {
                    item.DataModels = string.Join(",", entity.MetadataCode);
                }
            }
            if (!string.IsNullOrEmpty(method.JSFunc) &&
                (method.JSFunc.Equals(("@entity" + entity.MetadataCode), StringComparison.OrdinalIgnoreCase) ||
                method.JSFunc.Equals("#GetList", StringComparison.OrdinalIgnoreCase))
                )
            {
                item.IsLeaf = false;
                var currentCode = "Current";
                //如果List下面没有Current需要先构造Current节点
                if (!item.Code.Equals(currentCode, StringComparison.OrdinalIgnoreCase))
                {
                    var currentNode = new ExprItem()
                    {
                        ID = currentCode,
                        Code = currentCode,
                        Name = currentCode,
                        DataModels = entity.MetadataCode,
                        DisplayName = item.DisplayName + "." + currentCode,
                        ExprMetaDataID = item.ExprMetaDataID,
                        IsLeaf = false,
                        ItemType = ItemType.Object,
                        ParentID = item.ID,
                        SortOrder = 0,
                        ValueType = DataType.Record,
                        Children = new List<ExprItem>(),
                        RefSchemaExpr = RefSchemaExprUtil.GetExpr(entity.RefSchemaExpr),
                    };
                    //构造Current下级的Entity结构
                    BuildTEntityExprItem(currentNode, entity, IsContainExt, metaDataContent: metaDataContent);
                    item.Children = new List<ExprItem>() { currentNode };
                }
                else
                {
                    //构造Current下级的Entity结构
                    BuildTEntityExprItem(item, entity, IsContainExt);
                }
            }
            else
            {
                if (method.SubMethods != null && method.SubMethods.Count > 0)
                {
                    method.SubMethods.ForEach(m =>
                    {
                        BuildListTypeMethodExprItem(item, m, entity, IsContainExt: IsContainExt);
                    });
                }
            }
            parentItem.Children.Add(item);
        }
        private void BuildTEntityExprItem(ExprItem parentItem, TEntity entity, bool IsContainExt = false, IMetaDataContent metaDataContent = null)
        {
            
            if (entity == null)
                return;
            //针对DQ有多个DO的情况，需要单独处理
            if (entity.MetadataType == TEntityType.DQ)
            {
                //处理一个DQ下有多个DO
                var subEntitys = entity.Attributes.FindAll(x => x.DataType == DataType.List || x.DataType == DataType.Record);
                if (subEntitys != null && subEntitys.Count > 1)
                {
                    var itemIndex = 0;
                    foreach (TAttribute item in subEntitys)
                    {
                        var itemNode = new ExprItem()
                        {
                            ID = item.Entity.MetadataID,
                            Code = item.Entity.MetadataCode,
                            Name = item.Entity.MetadataName,
                            DisplayName = parentItem.DisplayName + "." + item.Entity.MetadataCode,
                            DataModels = item.Entity.MetadataCode,
                            HelpInfo = item.Entity.MetadataCode,
                            SortOrder = itemIndex,
                            ValueType = item.Entity.ResultType,
                            ExprMetaDataID = parentItem.ExprMetaDataID,
                            ParentID = parentItem.ID,
                            ItemType = GetItemTypeByTEntityType(item.Entity.MetadataType),
                            RefSchemaExpr = RefSchemaExprUtil.GetExpr(item.Entity.RefSchemaExpr),
                            IsLeaf = false,
                        };
                        if (item.Entity.Attributes != null && item.Entity.Attributes.Count > 0)
                        {
                            if (item.Entity.ResultType == DataType.List)
                            {
                                //增加List节点
                                item.Entity.ListTypeMethods.OrderBy(x => x.SortOrder).ToList().ForEach(method =>
                                {
                                    BuildListTypeMethodExprItem(itemNode, method, item.Entity, isRoot: true, IsContainExt: IsContainExt, attr: item);
                                });
                            }
                            else
                            {
                                BuildPropertyExprItem(itemNode, item.Entity, IsContainExt, metaDataContent);
                            }
                        }
                        parentItem.Children.Add(itemNode);
                        itemIndex++;
                    }
                }
                //处理一个DQ下只有一个DO
                else if (subEntitys != null && subEntitys.Count.Equals(1))
                {
                    if (subEntitys[0].Entity.Attributes != null && subEntitys[0].Entity.Attributes.Count > 0)
                    {
                        BuildTEntityExprItem(parentItem, subEntitys[0].Entity, metaDataContent: metaDataContent);
                    }
                }
                //处理Attribute
                var attributes = entity.Attributes.FindAll(x => x.DataType != DataType.List && x.DataType != DataType.Record);
                if (attributes != null && attributes.Count > 0)
                {
                    var attrIndex = 0;
                    foreach (TAttribute attr in attributes)
                    {
                        //跳过辅助语言字段
                        if (attr.IsNeedHideField(base.IsDev)) continue;
                        var itemNode = new ExprItem()
                        {
                            ID = attr.ID,
                            Code = attr.Code,
                            Name = attr.Name,
                            DisplayName = parentItem.DisplayName + "." + attr.Code,
                            HelpInfo = attr.Code,
                            SortOrder = attrIndex,
                            ValueType = attr.DataType,
                            ExprMetaDataID = parentItem.ExprMetaDataID,
                            ParentID = parentItem.ID,
                            ItemType = GetItemTypeByTEntityType(TEntityType.Attribute),
                            RefSchemaExpr = RefSchemaExprUtil.GetExpr(attr.RefSchemaExpr),
                        };
                        parentItem.Children.Add(itemNode);
                        attrIndex++;
                    }
                }
            }
            //针对非DQ的,主节点不需要体现,直接体现属性字段
            else
            {
                if (entity.Attributes != null && entity.Attributes.Count > 0)
                {
                    BuildPropertyExprItem(parentItem, entity, IsContainExt, metaDataContent);
                }
            }
        }

        private ItemType GetItemTypeByTEntityType(TEntityType eType)
        {
            switch (eType)
            {
                case TEntityType.DO:
                    return ItemType.DO;
                case TEntityType.CDO:
                    return ItemType.DO;
                case TEntityType.SGEO:
                case TEntityType.EO:
                    return ItemType.EO;
                case TEntityType.Attribute:
                    return ItemType.Attribute;
                default:
                    return ItemType.Object;

            }
        }

        /// <summary>
        /// 构造属性表达式项
        /// </summary>
        /// <param name="parentItem"></param>
        /// <param name="entity"></param>
        /// <param name="IsContainExt"></param>
        /// <param name="metaDataContent"></param>
        private void BuildPropertyExprItem(ExprItem parentItem, TEntity entity, bool IsContainExt = false, IMetaDataContent metaDataContent = null)
        {
            
            if (entity == null || entity.Attributes == null || entity.Attributes.Count <= 0)
                return;
            var proIndex = 0;
            /*
             * 特殊处理Action为CDO Action时，返回值的TEntity中的路径表达式为CDO的情况，此时GetExprValue应该从CDO|DO的元数据中获取。
             * 为了减少根据引用表达式GetExprValue时调用GetMetaData的次数，在这里先将MetaData取出来复用
             */
            IMetaData refExprSourceMetaData = null;                         //action所属的CDO MetaData
            IMetaDataContent refExprSourceMetaDataContent = null;           //action所属的CDO MetaDataContent
            IRefSchemaEntity refExprSourceMetaDataRefSchemaEntity = null;   //action所属的CDO MetaData 的 RefSchemaEntity
            IRefSchemaEntity metaDataContentRefSchemaEntity = null;         //其他普通的 MetaDataContent 的 RefSchemaEntity
            if (metaDataContent != null)
            {
                //特殊处理CDO Action
                if (metaDataContent is ActionMetaData action && entity.RefSchemaExpr.StartsWith("Schema.CDO"))
                {
                    refExprSourceMetaData = GetMetaData(action.RelatedMetaDataID, action.ProjectBranchID);
                    refExprSourceMetaDataContent = refExprSourceMetaData?.Content;
                }
                else if (metaDataContent is CompositeDataObject cdo)
                {
                    refExprSourceMetaData = GetMetaData(cdo.MetaDataID, cdo.ProjectBranchID);
                    refExprSourceMetaDataContent = metaDataContent;
                }
                else
                {
                    metaDataContentRefSchemaEntity = RefSchemaExprUtil.GetRefSchemaEntity(metaDataContent);
                }
            }
            if (refExprSourceMetaDataContent != null)
            {
                refExprSourceMetaDataRefSchemaEntity = RefSchemaExprUtil.GetRefSchemaEntity(refExprSourceMetaDataContent);
            }

            var attrList = entity.Attributes.OrderBy(x => x.SortOrder).ToList();
            foreach (TAttribute attr in attrList)
            {
                if (attr.DataType == DataType.Record)
                {
                    if (attr.Entity == null)
                        continue;
                    var pRecordNode = new ExprItem()
                    {
                        ID = attr.Entity.MetadataType.Equals(TEntityType.EO) ? attr.Code : attr.Entity.MetadataCode,
                        Code = attr.Entity.MetadataType.Equals(TEntityType.EO) ? attr.Code : attr.Entity.MetadataCode,
                        Name = attr.Entity.MetadataType.Equals(TEntityType.EO) ? attr.Name : attr.Entity.MetadataName,
                        //DisplayName = parentItem.DisplayName + "." + TUtil.GetPropertyName(attr.Entity.MetadataCode,false),
                        DisplayName = parentItem.DisplayName + "." + (attr.Entity.MetadataType.Equals(TEntityType.EO) ? attr.Code : attr.Entity.MetadataCode),
                        DataModels = attr.Entity.MetadataCode,
                        ExprMetaDataID = parentItem.ExprMetaDataID,
                        ItemType = ItemType.Object,
                        HelpInfo = attr.Name,
                        SortOrder = proIndex,
                        ValueType = DataType.Record,
                        RefSchemaExpr = RefSchemaExprUtil.GetExpr(attr.Entity.RefSchemaExpr),
                        IsLeaf = false,
                    };
                    BuildPropertyExprItem(pRecordNode, attr.Entity, IsContainExt, metaDataContent);
                    parentItem.Children.Add(pRecordNode);
                }
                else if (attr.DataType == DataType.List)
                {
                    if (attr.Entity == null)
                        continue;
                    //增加List节点
                    attr.Entity.ListTypeMethods.OrderBy(x => x.SortOrder).ToList().ForEach(method =>
                    {
                        BuildListTypeMethodExprItem(parentItem, method, attr.Entity, IsContainExt: IsContainExt, attr: attr);
                    });
                }
                else
                {
                    //跳过辅助语言字段
                    if (attr.IsNeedHideField(base.IsDev)) continue;
                    var pNode = new ExprItem()
                    {
                        ID = attr.ID,
                        Code = attr.Code,
                        Name = attr.Name,
                        DisplayName = parentItem.DisplayName + "." + attr.Code,
                        ItemType = ItemType.Attribute,
                        HelpInfo = parentItem.DisplayName + "." + attr.Code,
                        SortOrder = proIndex,
                        ValueType = attr.DataType,
                        ExprMetaDataID = parentItem.ExprMetaDataID,
                        IsLeaf = true,
                        RefSchemaExpr = RefSchemaExprUtil.GetExpr(attr.RefSchemaExpr),
                    };
                    if (metaDataContent != null)
                    {
                        //特殊处理CDO Action
                        if (refExprSourceMetaData != null)
                        {
                            pNode.RefSchemaExprValue = RefSchemaExprUtil.GetExprValue(refExprSourceMetaData, attr.RefSchemaExpr, true, refExprSourceMetaDataRefSchemaEntity);
                        }
                        else
                        {
                            if (metaDataContentRefSchemaEntity != null)
                                pNode.RefSchemaExprValue = RefSchemaExprUtil.GetExprValue(metaDataContentRefSchemaEntity, attr.RefSchemaExpr, true);
                        }
                    }
                    //是否需要包含扩展属性
                    if (IsContainExt)
                    {
                        var extDic = new Dictionary<string, object>();
                        extDic.Add(ExpressionPluginManager.ExprExt_Length, attr.Length);
                        extDic.Add(ExpressionPluginManager.ExprExt_IsRequired, attr.IsRequired);
                        extDic.Add(ExpressionPluginManager.ExprExt_Precision, attr.Precision);
                        extDic.Add(ExpressionPluginManager.ExprExt_DefaultValue, attr.DefaultValue);
                        extDic.Add(ExpressionPluginManager.ExprExt_AttributeType, attr.AttributeType);
                        if (attr.ExtProperties != null && attr.ExtProperties.Count > 0)
                        {
                            foreach (var key in attr.ExtProperties.Keys)
                            {
                                extDic.Add(key, attr.ExtProperties[key]);
                            }
                            //ExpressionPluginManager.ExprExtList.ForEach(ext=>
                            //{
                            //    if (attr.ExtProperties.ContainsKey(ext))
                            //    {
                            //        extDic.Add(ext,attr.ExtProperties[ext]);
                            //    }
                            //});
                        }


                        pNode.ExprExt = extDic;
                    }
                    parentItem.Children.Add(pNode);
                }
                proIndex++;
            }
        }

        private void UpdateHelpInfo(ExprItem item)
        {
            switch (item.ItemType)
            {
                case ItemType.Action:
                    {
                        StringBuilder helpInfo = new StringBuilder();
                        //helpInfo.Append($"Action:<b>{item.Code}</b> DataType <b>{item.DataModels}</b><br/>");
                        //helpInfo.Append("<br/>");
                        //helpInfo.Append($"Params:<br/>");
                        helpInfo.Append($"<div ad><div at>服务动作：</div>{item.Code}，{item.Name}</div>");
                        helpInfo.Append($"<div ad><div at>返回值类型：</div>{item.ValueType}</div>");
                        if(item.ExprFuncItemParamList!=null && item.ExprFuncItemParamList.Count > 0)
                        {
                            helpInfo.Append($"<div ad><div at>入参：</div>"); 
                            foreach (var param in item.ExprFuncItemParamList)
                            {
                                //helpInfo.Append($"<b>{p.Code}</b> DataType: <b>{p.DataType}</b><br/>");
                                helpInfo.Append($"{param.Code}, 类型：{param.DataType}<br/>");
                            }
                            helpInfo.Append($"</div>");
                        }
                        // helpInfo.Append("<br/>");
                        // helpInfo.Append($"ReturnValueType:<b>{item.ValueType}</b><br/>");
                        item.HelpInfo = helpInfo.ToString();
                    }
                    break;
                case ItemType.Attribute:
                    {
                        StringBuilder helpInfo = new StringBuilder();
                        // helpInfo.Append($"<b>{item.Code}</b> DataType <b>{item.ValueType}</b><br/>");
                        helpInfo.Append($"<div ad><div at>属性：</div>{item.Code}，{item.Name}</div>");
                        helpInfo.Append($"<div ad><div at>类型：</div>{item.ValueType}</div>");
                        item.HelpInfo = helpInfo.ToString();
                    }
                    break;
                case ItemType.DO:
                    {
                        StringBuilder helpInfo = new StringBuilder();
                        helpInfo.Append($"<div ad><div at>数据对象：</div>{item.DataModels}</div>");
                        helpInfo.Append($"<div ad><div at>返回值类型：</div>DO</div>");
                        // helpInfo.Append($"DataType <b>{item.DataModels} DO</b><br/>");
                        item.HelpInfo = helpInfo.ToString();
                    }
                    break;
                case ItemType.EO:
                    {
                        StringBuilder helpInfo = new StringBuilder();
                        helpInfo.Append($"<div ad><div at>实体对象：</div>{item.DataModels}</div>");
                        helpInfo.Append($"<div ad><div at>返回值类型：</div>EO</div>");
                        // helpInfo.Append($"DataType <b>{item.DataModels} EO</b><br/>");
                        item.HelpInfo = helpInfo.ToString();
                    }
                    break;
                case ItemType.Object:
                    {
                        StringBuilder helpInfo = new StringBuilder();
                        
                        if (item.ValueType == DataType.List)
                        {
                            //helpInfo.Append($"DataType <b>{item.DataModels} List</b><br/>");
                            helpInfo.Append($"<div ad><div at>对象：</div>List&lt;{item.DataModels}&gt;</div>");
                        }
                        else if (item.ValueType == DataType.Record)
                        {
                            //helpInfo.Append($"DataType <b>{item.DataModels} Record</b><br/>");
                            helpInfo.Append($"<div ad><div at>对象：</div>Record&lt;{item.DataModels}&gt;</div>");
                        }
                        else
                        {
                            //helpInfo.Append($"DataType <b>{item.ValueType}</b><br/>");
                            helpInfo.Append($"<div ad><div at>对象：</div>{item.DataModels}</div>");
                        }
                        helpInfo.Append($"<div ad><div at>返回值类型：</div>{item.ValueType}</div>");
                        item.HelpInfo = helpInfo.ToString();
                    }
                    break;
            }
            if (item.Children != null)
            {
                item.Children.ForEach(c => UpdateHelpInfo(c));
            }
        }
        #endregion
    }
}
